/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_components/zhiqim_admin.htm
 *
 * Zhiqim Admin is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.manager.presenter;

import java.util.List;

import org.zhiqim.httpd.HttpContext;
import org.zhiqim.httpd.HttpCookie;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpResponse;
import org.zhiqim.httpd.context.ZmlBootstrap;
import org.zhiqim.httpd.context.ZmlContexts;
import org.zhiqim.httpd.context.core.Context;
import org.zhiqim.httpd.util.Sessions;
import org.zhiqim.httpd.validate.ones.IsNotEmpty;
import org.zhiqim.httpd.validate.ones.IsNumericLen;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.model.codes.Base64;
import org.zhiqim.kernel.model.codes.RSA;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.manager.ZmrBootstrap;
import org.zhiqim.manager.ZmrBootstrapApi;
import org.zhiqim.manager.ZmrConstants;
import org.zhiqim.manager.ZmrPassworder;
import org.zhiqim.manager.ZmrSessionUser;
import org.zhiqim.manager.dao.ZmrOperatorDao;
import org.zhiqim.manager.dao.ZmrParamDao;
import org.zhiqim.manager.dbo.ZmrMenu;
import org.zhiqim.manager.dbo.ZmrOperator;
import org.zhiqim.orm.ORM;

/**
 * 登陆控制器
 *
 * @version v1.0.0 @author liuhu 2018-8-2 新建与整理
 */
@AnAlias("ZmrLoginPresenter")
public class ZmrLoginPresenter implements ZmrConstants
{
    public static void doLogin(HttpRequest request) throws Exception
    {
        HttpContext context = request.getContext();
        //1.判断传入参数
        request.addValidate(new IsNotEmpty("operatorCode", "用户名不能为空"));
        request.addValidate(new IsNotEmpty("operatorPass", "密码不能为空"));
        
        if(ZmrParamDao.hasVerificationCode()){
            request.addValidate(new IsNumericLen("verificationCode", "验证码必须是4位数字", 4, 4));
        }
        if (!request.chkValidate())
        {
            request.setResponseError(request.getAlertMsg());
            return;
        }
        
        //2.验证码
        if(ZmrParamDao.hasVerificationCode())
        {
            String verificationCode = request.getParameter("verificationCode");
            if(verificationCode.length() != 4)
            {
                request.setResponseError("验证码必须是4位数字");
                return;
            }
            String vcode = Sessions.getSessionVerificationCode(request);
            if (!verificationCode.equals(vcode))
            {
                request.setResponseError("验证码不正确或已失效，请新输入！");
                return;
            }
        }
        
        //3.验证操作员编码是否存在、是否停用，是否组停用
        String operatorCode = request.getParameter("operatorCode");
        ZmrOperator operator = ORM.table().item(ZmrOperator.class, operatorCode);
        if(operator == null)
        {
            request.setResponseError("用户名不正确");
            return;
        }
        
        if(operator.getOperatorStatus() == 1)
        {
            request.setResponseError("该用户已停用，不允许登录");
            return;
        }
        
        //4.验证密码
        String operatorPass = request.getParameter("operatorPass");
        
        byte[] operatorPassByte = Base64.decode(operatorPass);
        String privateKey = ZmrParamDao.getPrivateKey();
        byte[] operatorPassDecrypt = RSA.decrypt(operatorPassByte, privateKey);
        operatorPass = new String(operatorPassDecrypt, _UTF_8_C_);
        
        if (isValidateRememberPass(operatorPass))
        {//全是●的密码表示记住密码要求验证密钥
            if (!ZmrParamDao.hasRememberCode() || !ZmrParamDao.hasRememberPass() || !operatorCode.equals(request.getCookie("operatorCode")))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
            
            ZmrPassworder passworder = ZmrBootstrap.getPassworder();
            String operatorPassSecr = request.getCookie("operatorPass");
            if (!passworder.secretChk(operatorCode, operatorPass, operator.getOperatorPassSalt(), operatorPassSecr))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
        }
        else
        {//正常验证密码
            if(!ZmrOperatorDao.validatePassword(operator, operatorPass))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
        }
        
        List<ZmrMenu> menuList = ZmrOperatorDao.getOperatorMenuList(operator);
        if(menuList.isEmpty())
        {
            request.setResponseError("您暂没有任何操作权限，请与管理员联系");
            return;
        }
        
        //5.完成验证，组装会话用户
        ZmrSessionUser sessionUser = new ZmrSessionUser()
            .initOperator(operator)
            .initMenuList(request.getContext(), menuList);
        
        //6.判断需要保存信息到COOKIE
        if(ZmrParamDao.hasRememberCode())
        {
            String rememberCode = request.getParameter("rememberCode");
            String rememberPass = request.getParameter("rememberPass");
            int day30 = 60*60*24*30;
            
            HttpResponse response = request.getResponse();
            if(Validates.isNotEmpty(rememberPass))
            {//勾选了记住密码，则一定记住登录名
                ZmrPassworder passworder = ZmrBootstrap.getPassworder();
                String operatorSecr = passworder.secret(operatorCode, operatorPass, operator.getOperatorPassSalt());
                response.addCookie(new HttpCookie("operatorCode", operatorCode, day30));
                response.addCookie(new HttpCookie("operatorPass", operatorSecr, day30));
            }
            else if (Validates.isNotEmpty(rememberCode))
            {//只记住用户名
                response.addCookie(new HttpCookie("operatorCode", operatorCode, day30));
                response.addCookie(new HttpCookie("operatorPass", "", day30));
            }
            else
            {//否则设置值为空
                response.addCookie(new HttpCookie("operatorCode", "", day30));
                response.addCookie(new HttpCookie("operatorPass", "", day30));
            }
        }
        
        //7.判断是否填写了主页跳转地址
        String mainParamUrl = request.getRootPath(ZmlContexts.parseZmlContent(request, ZmrParamDao.getMainUrl()));
        if (!ZmrParamDao.isThemeFrame())
        {
            request.bindSessionUser(sessionUser);
            request.setResponseResult(mainParamUrl);
        }
        else
        {
            String welcomeUrl = request.getRootPath(ZmlContexts.parseZmlContent(request, ZMR_MAIN_URL_WELCOME));
            String mainDefaultUrl = request.getRootPath(ZmlContexts.parseZmlContent(request, ZMR_MAIN_URL_DEFAULT));
            sessionUser.initWelcomeUrl(welcomeUrl);
            sessionUser.initMainUrl(mainDefaultUrl.equals(mainParamUrl)?welcomeUrl:mainParamUrl);
            
            request.bindSessionUser(sessionUser);
            request.setResponseResult(mainDefaultUrl);
        }
        
        //8.最后回调登录
        ZmlBootstrap bootstrap = ((Context) context).getBootstrap();
        if (bootstrap instanceof ZmrBootstrapApi)
        {
            ((ZmrBootstrapApi)bootstrap).logined(request);
        }
    }
    
    private static boolean isValidateRememberPass(String operatorPass)
    {
        for (int i=0;i<operatorPass.length();i++)
        {
            if (operatorPass.charAt(i) != '●')
                return false;
        }
        return true;
    }
}
